﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public static class UnityFunctions  {

    public static void ClearList(List<Transform> _list)
    {
        if (_list != null)
        {
            for (int i = 0; i < _list.Count; i++)
            {
#if UNITY_EDITOR
                if (_list[i] != null)
                    GameObject.DestroyImmediate(_list[i].gameObject);
#endif
                if (_list[i] != null)
                    GameObject.Destroy(_list[i].gameObject);

            }
            _list.Clear();
        }
    }


    public static void ClearList(List<GameObject> _list)
    {
        if (_list != null)
        {
            for (int i = 0; i < _list.Count; i++)
            {
#if UNITY_EDITOR
                if (_list[i] != null)
                    GameObject.DestroyImmediate(_list[i].gameObject);
#endif
                if (_list[i] != null)
                    GameObject.Destroy(_list[i].gameObject);

            }
            _list.Clear();
        }
    }

    public static void ClearList<T>(List<T> _list) where T : MonoBehaviour
    {
        if (_list != null)
        {
            for (int i = 0; i < _list.Count; i++)
            {
#if UNITY_EDITOR
                if (_list[i] != null)
                    GameObject.DestroyImmediate(_list[i].gameObject);
#endif
                if (_list[i] != null)
                    GameObject.Destroy(_list[i].gameObject);

            }
            _list.Clear();
        }
    }

    public static long GetTimeStampSeconds()
    {
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
        return (long)ts.TotalSeconds;
    }

    public static DateTime TimeStampSeconds2DateTime(long timeStamp)
    {
        //GameDebug.LogError($"TimeStampSeconds2DateTime timeStamp:{timeStamp}  GetTimeStampSeconds():{GetTimeStampSeconds()}");
        return new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(timeStamp);
    }
    
    /// <summary>
    /// 时间转换天时分秒显示
    /// </summary>
    /// <returns>The stamp to HM.</returns>
    /// <param name="seconds">seconds</param>
    public static string TimeToDHMS(double secondsd)
    {
        var seconds = (int)secondsd;
        var day = seconds / 86400;
        var secondsInDay = seconds % 86400;
        var hour = secondsInDay / 3600;
        var minute = (secondsInDay - hour * 3600) / 60;
        var second = secondsInDay - hour * 3600 - minute * 60;
        if (day > 0)
        {
            return string.Format("{0}d {1:D2}:{2:D2}:{3:D2}", day, hour, minute, second);
        }
        else
        {
            return string.Format("{0:D2}:{1:D2}:{2:D2}", hour, minute, second);
        }
    }
    public static void TimeToDHMS(double secondsd,out int day,out int hour,out int minute,out int second)
    {
        var seconds = (int)secondsd;
        day = seconds / 86400;
        int secondsInDay = seconds % 86400;
        hour = secondsInDay / 3600;
        minute = (secondsInDay - hour * 3600) / 60;
        second = secondsInDay - hour * 3600 - minute * 60;
    }

    public static string GetTimeElapsed(long timestamp)
    {
        int elaSec = (int)(UnityFunctions.GetTimeStampSeconds() - timestamp);

        UnityFunctions.TimeToDHMS(elaSec, out int day, out int hour, out int min, out int sec);

        if (day > 0)
        {
            return $"{day}天";
        }
        else if (hour > 0)
        {
            return $"{hour}小时";
        }
        else if (min > 0)
        {
            return $"{min}分钟";
        }
        else //if (elaSec > 0)
        {
            elaSec = elaSec / 10 * 10;
            return $"{elaSec}秒";
        }
    }

    public static string TimeToMS(double secondsd)
    {
        var seconds = (int)secondsd;
        var minute = seconds / 60;
        var second = seconds - minute * 60;
        return string.Format("{0:D2}:{1:D2}", minute, second);
    }

    public static DateTime GetTimeZoneDateTime(long timestamp)
    {
        DateTime utcDate = DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
        TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
        DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(utcDate, timeZone);
        return localTime;
    }
    public static DateTime GetTimeZoneNowDateTime()
    {
        TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
        DateTime utcNow = DateTime.Now.ToUniversalTime();
        DateTime localTime = TimeZoneInfo.ConvertTimeFromUtc(utcNow, timeZone);
        return localTime;
    }

    public static Transform FindInChild(Transform trans, string name)
    {
        var ts = trans.GetComponentsInChildren<Transform>();
        foreach (var t in ts)
        {
            if (t.name == name)
                return t;
        }
        return null;
    }

    public static void SetLayerWithChilds(GameObject gameObject,int layer)
    {
        var ts = gameObject.GetComponentsInChildren<Transform>();
        foreach (var t in ts)
        {
            t.gameObject.layer = layer;

        }
    }

    /// <summary>
    /// 名字只显示八位
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public static string GetShowedName(string name,bool showExtend)
    {
        if (string.IsNullOrEmpty(name)) 
            return "";
        
        if (name.Length > 9)
        {
            name = name.Substring(0, 8);
            if (showExtend)
                name += "...";
        }
        return name;
    }

    public static void SetGameObjLayer(GameObject gameObject, int layerChild)
    {
        foreach (var transform in gameObject.GetComponentsInChildren<Transform>())
        {
            transform.gameObject.layer = layerChild;
        }
    }

    /// <summary>
    /// 旋转
    /// </summary>
    /// <param name="trans"></param>
    /// <param name="center"></param>
    /// <param name="angle"></param>
    public static Vector3 ClockwiseRotateAround(Vector3 pos, Vector3 center, float angle)
    {
        Vector3 p = pos - center;
        Quaternion m = Quaternion.AngleAxis(angle, Vector3.back);
        return center + m * p;
    }  
   
    /*public static Vector3 RotatePoint(Vector3 worldPoint, Vector3 origin, Vector3 axis,float radian)
    {
        Vector3 relativePos = worldPoint - origin;

        Matrix4x4 r = GetRotateMatrix(axis * radian);
        Vector4 p = new Vector4(relativePos.x, relativePos.y, relativePos.z, 1);
        Vector4 temp = r * p;

        Vector3 res = origin + new Vector3(temp.x, temp.y, temp.z);
        //GameDebug.Log($"旋转矩阵 \n{r} \n乘以 向量{p} 得到：{temp}  返回结果:{res}");
        return res;
    }
    public static Matrix4x4 GetRotateMatrix(Vector3 rotate)
    {
        Matrix4x4 zM = GetRotateZMatrix(rotate.z);
        Matrix4x4 yM = GetRotateYMatrix(rotate.y);
        Matrix4x4 xM = GetRotateXMatrix(rotate.x);
        
        Matrix4x4 r = yM * xM * zM;
        // GameDebug.Log($"矩阵 \n{r} \n乘以 矩阵{yM}\n乘以 矩阵\n{yM} 得到：\n{r} ");
        return r;
    }
    public static Matrix4x4 GetRotateXMatrix(float alpha)
    {
        while (alpha < 0)
            alpha += 2 * Mathf.PI;

        alpha %= 2 * Mathf.PI;

        Matrix4x4 RotateXMatrix = new Matrix4x4();
        RotateXMatrix[1, 1] = 1;
        RotateXMatrix[2, 2] = Mathf.Cos(alpha);
        RotateXMatrix[2, 3] = -Mathf.Sin(alpha);
        RotateXMatrix[3, 2] = Mathf.Sin(alpha);
        RotateXMatrix[3, 3] = Mathf.Cos(alpha);
        RotateXMatrix[4, 4] = 1;
        return RotateXMatrix;
    }
    public static Matrix4x4 GetRotateYMatrix(float alpha)
    {
        while (alpha < 0)
            alpha +=  2 * Mathf.PI;

        Matrix4x4 RotateYMatrix = new Matrix4x4();
        RotateYMatrix[1, 1] = Mathf.Cos(alpha);
        RotateYMatrix[1, 3] = Mathf.Sin(alpha);
        RotateYMatrix[2, 2] = 1;
        RotateYMatrix[3, 1] = -Mathf.Sin(alpha);
        RotateYMatrix[3, 3] = Mathf.Cos(alpha);
        RotateYMatrix[4, 4] = 1;
        return RotateYMatrix;
    }

    public static Matrix4x4 GetRotateZMatrix(float alpha)
    {
        while (alpha < 0)
            alpha +=  2 * Mathf.PI;

        Matrix4x4 RotateYMatrix = new Matrix4x4();
        RotateYMatrix[1, 1] = Mathf.Cos(alpha);
        RotateYMatrix[1, 2] = -Mathf.Sin(alpha);
        RotateYMatrix[2, 1] = Mathf.Sin(alpha);
        RotateYMatrix[2, 2] = Mathf.Cos(alpha);
        RotateYMatrix[3, 3] = 1;
        RotateYMatrix[4, 4] = 1;
        return RotateYMatrix;
    }*/

    public static float FloatRound(float value, int round)
    {
        return (int)(value * round) / (float)round;
    }
    
    public static bool CheckBlockWithObj(Vector3 fromPos, Vector3 toPos,out RaycastHit hit,LayerMask layer)
    {
        Vector3 checkBeginPos = fromPos;
        Vector3 checkVec = toPos - fromPos;

        checkBeginPos.y = 1;
        checkVec.y = 0;
        
        Ray checkRay = new Ray(checkBeginPos,checkVec);

        bool rayCast = Physics.Raycast(checkRay,out hit , checkVec.magnitude,layer);

        if (rayCast)
        {
//          GameDebug.LogShowy($"检测碰撞到墙壁:{hit.collider.gameObject.name}");
            return true;
        }
        return false;
    }
    public static Sprite GetSpriteWithByte(Tex tex)
    {
        return GetSpriteWithByte(tex.texWidth, tex.texHeight, tex.tex);
    }
    public static Sprite GetSpriteWithByte(int width, int height, byte[] bytes)
    {
        if (bytes == null || bytes.Length <= 0)
            return null;

        var iconTexture = new Texture2D(width, height);
        iconTexture.LoadImage(bytes);
        Sprite Spr = Sprite.Create(iconTexture, new Rect(0, 0, iconTexture.width, iconTexture.height), new Vector2(0.5f, 0.5f));
        //GameObject.DestroyImmediate(iconTexture);
        NewTextureController.instance.AddNewTexture(iconTexture, Spr);
        return Spr;
    }
    //public static void GetTextureWithByte(string url, Action<Texture2D> onGetTex)
    //{
    //    GetTextureWithUrl(url, onGetTex);
    //}
    public static void GetTextureWithUrl(string url, Action<Texture2D> onGetTex)
    {
        if (string.IsNullOrEmpty(url))
            onGetTex?.Invoke(null);

        MGame.instance.StartCoroutine(LoadImage(url, onGetTex));
    }
    static IEnumerator LoadImage(string imageURL,Action<Texture2D> onGetTex)
    {
        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(imageURL))
        {
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.LogError("Failed to load image: " + www.error+"\n"+imageURL);
            }
            else
            {
                // 获取加载的Texture2D
                Texture2D texture = DownloadHandlerTexture.GetContent(www);
                onGetTex?.Invoke(texture);
            }
        }
    }
    public static Texture2D GetTextureWithData(Tex tex)
    {
        return GetTextureWithByte(tex.texWidth, tex.texHeight, tex.tex);
    }
    public static Texture2D GetTextureWithByte(int width, int height, byte[] bytes)
    {
        if (bytes == null || bytes.Length <= 0)
            return null;

        var texture = new Texture2D(width, height);
        texture.LoadImage(bytes);
        //NewTextureController.instance.AddNewTexture(texture, null);
        return texture;
    }

    public static Vector2 SetRawImage(RawImage rawImage,Texture2D texture,float rawImageOriginalSize,bool fillSize = false)
    {
        Vector2 size = Vector2.zero;
        if (rawImage == null) 
            return size;

        rawImage.texture = texture;

        if (texture != null)
        {
            var rectTransform = rawImage.rectTransform;

            rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
            rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
            rectTransform.pivot = new Vector2(0.5f, 0.5f);

            if (fillSize)
            {
                if (texture.width > texture.height)
                {
                    float rate = (float)texture.width / texture.height;
                     size = new Vector2(rawImageOriginalSize * rate, rawImageOriginalSize);

                    rectTransform.sizeDelta = size;
                }
                else
                {
                    float rate = (float)texture.height / texture.width;
                     size = new Vector2(rawImageOriginalSize, rawImageOriginalSize * rate);

                    rectTransform.sizeDelta = size;
                }
            }
            else
            {
                if (texture.width > texture.height)
                {
                    float rate = (float)texture.width / texture.height;
                     size = new Vector2(rawImageOriginalSize, rawImageOriginalSize / rate);

                    rectTransform.sizeDelta = size;
                }
                else
                {
                    float rate = (float)texture.height / texture.width;
                     size = new Vector2(rawImageOriginalSize / rate, rawImageOriginalSize);

                    rectTransform.sizeDelta = size;
                }
            }
        }
        return size;
    }

    public static IEnumerator AdjustItemsLayout(Transform trans)
    {
        int index = 0;

        var hlgs = trans.GetComponentsInChildren<HorizontalLayoutGroup>();
        var vlgs = trans.GetComponentsInChildren<VerticalLayoutGroup>();
        var glgd = trans.GetComponentsInChildren<GridLayoutGroup>();

        while (index <= 10)
        {
            if (!trans.gameObject.activeInHierarchy) 
                yield break;

            float value = index % 2 == 0 ? 0.001f : -0.001f;

            foreach (var hlg in hlgs)
            {
                //if(hlg)
                //    hlg.spacing += value;
                LayoutRebuilder.ForceRebuildLayoutImmediate(hlg.GetComponent<RectTransform>());
            }
            foreach (var vlg in vlgs)
            {
                //if (vlg)
                //    vlg.spacing += value;
                LayoutRebuilder.ForceRebuildLayoutImmediate(vlg.GetComponent<RectTransform>());
            }
            foreach (var vlg in glgd)
            {
                //if (vlg)
                //    vlg.spacing = new Vector2(vlg.spacing.x, vlg.spacing.y + value);
                LayoutRebuilder.ForceRebuildLayoutImmediate(vlg.GetComponent<RectTransform>());
            }

            index++;
            yield return new WaitForSeconds(0.1f);
        }
    }


}
